package com.yunda.AJDeviceService.utils;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.springframework.util.CollectionUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * HTTP 请求工具类
 *
 * @author : liii
 * @version : 1.0.0
 * @date : 2015/7/21
 * @see :
 */
@Slf4j
public class HttpUtil {
    private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(HttpUtil.class);
    private static PoolingHttpClientConnectionManager connMgr;
    private static RequestConfig requestConfig;
    private static final int MAX_TIMEOUT = 12000;

    static {
        // 设置连接池
        connMgr = new PoolingHttpClientConnectionManager();
        // 设置连接池大小
        connMgr.setMaxTotal(100);
        connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());

        RequestConfig.Builder configBuilder = RequestConfig.custom();
        // 设置连接超时
        configBuilder.setConnectTimeout(MAX_TIMEOUT);
        // 设置读取超时
        configBuilder.setSocketTimeout(MAX_TIMEOUT);
        // 设置从连接池获取连接实例的超时
        configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT);
        // 在提交请求之前 测试连接是否可用
        requestConfig = configBuilder.build();
    }

    /**
     * 发送 GET 请求（HTTP），不带输入数据
     *
     * @param url
     * @return
     */
    public static String doGet(String url) {
        return doGet(url, new HashMap<String, Object>(16));
    }

    /**
     * 发送 GET 请求（HTTP），K-V形式
     *
     * @param url
     * @param params
     * @return
     */
    public static String doGet(String url, Map<String, Object> params) {
        String apiUrl = url;
        StringBuffer param = new StringBuffer();
        int i = 0;
        for (String key : params.keySet()) {
            if (i == 0) {
                param.append("?");
            } else {
                param.append("&");
            }
            param.append(key).append("=").append(params.get(key));
            i++;
        }
        apiUrl += param;
        String result = null;
        HttpClient httpclient = HttpClients.createDefault();
        try {
            LOGGER.warn("发送GET请求URL : " + apiUrl);
            HttpGet httpPost = new HttpGet(apiUrl);
            HttpResponse response = httpclient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            LOGGER.warn("执行状态码 : " + statusCode);

            HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream instream = entity.getContent();
                result = IOUtils.toString(instream, "UTF-8");
            }
        } catch (IOException e) {
			log.error("调用出错：{}", e.getMessage());
        }
        return result;
    }


	/**
	 * 发送 GET 请求（HTTP），K-V形式
	 *
	 * @param url
	 * @param headerParams
	 * @return
	 */
	public static String doGet(Map<String, String> headerParams, String url) {
		String result = null;
		HttpClient httpclient = HttpClients.createDefault();
		try {
			LOGGER.warn("发送GET请求URL : " + url);
			HttpGet httpPost = new HttpGet(url);

			//请求头header
			if (!CollectionUtils.isEmpty(headerParams)) {
				for (Entry<String, String> headerEntry : headerParams.entrySet()) {
					httpPost.addHeader(headerEntry.getKey(), headerEntry.getValue());
				}
			}

			HttpResponse response = httpclient.execute(httpPost);
			int statusCode = response.getStatusLine().getStatusCode();
			LOGGER.warn("执行状态码 : " + statusCode);

			HttpEntity entity = response.getEntity();
			if (entity != null) {
				InputStream instream = entity.getContent();
				result = IOUtils.toString(instream, "UTF-8");
			}
		} catch (IOException e) {
			log.error("调用出错：{}", e.getMessage());
		}
		return result;

	}

    /**
     * 发送 GET 请求（HTTP），K-V形式
     *
     * @param url
     * @return
     */
    public static InputStream doGetInputStream(String url) {
        String apiUrl = url;
        InputStream instream = null;
        String content_type = null;
        HttpClient httpclient = HttpClients.createDefault();
        try {
            HttpGet httpPost = new HttpGet(apiUrl);
            HttpResponse response = httpclient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            Header[] header = response.getHeaders("Content-Type");
            content_type = header[0].getValue();

            log.debug("执行状态码 : {}", statusCode);

            HttpEntity entity = response.getEntity();
            if (entity != null) {
                instream = entity.getContent();
            }
        } catch (IOException e) {

        }
        return instream;
    }

    /**
     * 发送 POST 请求（HTTP），不带输入数据
     *
     * @param apiUrl
     * @return
     */
    public static String doPost(String apiUrl) {
        return doPost(apiUrl, new HashMap<String, Object>(16));
    }


    /**
     * 发送 POST 请求（HTTP），JSON形式
     *
     * @param apiUrl
     * @param json   json对象
     * @return
     */
    public static String doPost(String apiUrl, Object json) {
        return doPost(apiUrl, json, log);
    }


    /**
     * 发送 POST 请求（HTTP），JSON形式
     *
     * @param apiUrl
     * @param json   json对象
     * @return
     */
    public static String doPost(String apiUrl, Object json, Logger logger) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String httpStr = null;
        HttpPost httpPost = new HttpPost(apiUrl);
        CloseableHttpResponse response = null;

        try {
            httpPost.setConfig(requestConfig);
            //解决中文乱码问题
            StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");
            stringEntity.setContentEncoding("UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();

            logger.debug("执行状态码 : {}", response.getStatusLine().getStatusCode());
            httpStr = EntityUtils.toString(entity, "UTF-8");
        } catch (IOException e) {
            logger.error("HttpUtil.doPost error:", e);
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    logger.error("HttpUtil.doPost error:", e);
                }
            }
        }
        return httpStr;
    }


    /**
     * 发送POST请求（HTTP），Map形式
     *
     * @param url         请求url
     * @param headerMap   请求头header
     * @param formDataMap 请求体body->form-data
     * @return
     */
    public static String doPost(String url, Map<String, String> headerMap, Map<String, String> formDataMap) {
        return doPost(url, headerMap, formDataMap, null);
    }

    /**
     * 发送POST请求（HTTP），Map形式
     *
     * @param url         请求url
     * @param headerMap   请求头header
     * @param formDataMap 请求体body->form-data
     * @param bodyMap     请求体body->json，覆盖请求体body->form-data
     * @return
     */
    public static String doPost(String url, Map<String, String> headerMap, Map<String, String> formDataMap, Map<String, String> bodyMap) {
        return doPost(url, headerMap, formDataMap, bodyMap, log);
    }


    /**
     * 发送POST请求（HTTP），Map形式
     *
     * @param url         请求url
     * @param headerMap   请求头header
     * @param formDataMap 请求体body->form-data
     * @param bodyMap     请求体body->json，覆盖请求体body->form-data
     * @return
     */
    public static String doPost(String url, Map<String, String> headerMap, Map<String, String> formDataMap, Map<String, String> bodyMap, Logger logger) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String httpStr = null;
        HttpPost httpPost = new HttpPost(url);
        CloseableHttpResponse response = null;
        try {
            httpPost.setConfig(requestConfig);

            //请求头header
            if (!CollectionUtils.isEmpty(headerMap)) {
                for (Entry<String, String> headerEntry : headerMap.entrySet()) {
                    httpPost.addHeader(headerEntry.getKey(), headerEntry.getValue());
                }
            }

            //请求体body->form-data
            if (!CollectionUtils.isEmpty(formDataMap)) {
                List<NameValuePair> nvps = new ArrayList<>();
                for (Entry<String, String> formDataEntry : formDataMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(formDataEntry.getKey(), formDataEntry.getValue()));
                }

                httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
            }

            //请求体body->json
            if (!CollectionUtils.isEmpty(bodyMap)) {
                //解决中文乱码问题
                StringEntity stringEntity = new StringEntity(JSON.toJSONString(bodyMap), "UTF-8");
                stringEntity.setContentEncoding("UTF-8");
                stringEntity.setContentType("application/json");
                httpPost.setEntity(stringEntity);
            }

            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();

            log.debug("执行状态码 : {}", response.getStatusLine().getStatusCode());
            httpStr = EntityUtils.toString(entity, "UTF-8");
            log.debug("响应体 : {}", httpStr);
        } catch (IOException e) {
            log.error("HttpUtil.doPost error:", e);
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    log.error("HttpUtil.doPost error:", e);
                }
            }
        }
        return httpStr;
    }



    /**
     * 发送 SSL POST 请求（HTTPS），JSON形式
     *
     * @param apiUrl API接口URL
     * @param body   body对象
     * @return
     */
    public static String doPostJSONSSL(String apiUrl, String body) {
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
        HttpPost httpPost = new HttpPost(apiUrl);
        CloseableHttpResponse response = null;
        String httpStr = null;

        try {
            // 解决中文乱码问题
            StringEntity stringEntity = new StringEntity(body, "UTF-8");
            stringEntity.setContentEncoding("UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
            response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                return null;
            }
            HttpEntity entity = response.getEntity();
            if (entity == null) {
                return null;
            }
            httpStr = EntityUtils.toString(entity, "utf-8");
        } catch (Exception e) {

        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {

                }
            }
        }
        return httpStr;
    }


    /**
     * 发送 SSL Get 请求（HTTPS），JSON形式
     *
     * @param apiUrl API接口URL
     * @return
     */
    public static String doGetJSONSSL(String apiUrl) {
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
        HttpGet httpGet = new HttpGet(apiUrl);
        CloseableHttpResponse response = null;
        String httpStr = null;

        try {
            httpGet.setConfig(requestConfig);
            response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                return null;
            }
            HttpEntity entity = response.getEntity();
            if (entity == null) {
                return null;
            }
            httpStr = EntityUtils.toString(entity, "utf-8");
        } catch (Exception e) {

        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {

                }
            }
        }
        return httpStr;
    }

    /**
     * 下载文件并保存
     */
    public static void downloadFile() {

    }

    /**
     * 创建SSL安全连接
     *
     * @return
     */
    @SuppressWarnings("deprecation")
    private static SSLConnectionSocketFactory createSSLConnSocketFactory() {
        SSLConnectionSocketFactory sslsf = null;
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {

                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {

                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }

                @Override
                public void verify(String host, SSLSocket ssl) throws IOException {
                }

                @Override
                public void verify(String host, X509Certificate cert) throws SSLException {
                }

                @Override
                public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
                }
            });
        } catch (GeneralSecurityException e) {

        }
        return sslsf;
    }


    /**
     * 测试方法
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {

//        String data = "{    \"msg_src\": \"1\",    \"msg_src_sys\": \"nagios\",    \"agentid\": \"35\",    \"totag\": \"19\",    \"msgtype\": \"text\",    \"msgcontent\": \"IP地址: 10.0.65.214\n告警信息: DISK WARNING - free space: / 45173 MB (19% inode=99%):\n通知类型: PROBLEM\n主机: un65214\n服务:  chk_disk_yd\n状态: WARNING\n\n日期时间: 2016-06-24 15:50:09\",    \"safe\": \"0\"}";
//        System.out.println(URLDecoder.decode(data, "UTF-8"));

    }

    public static String doPostForm(String url, Map<String, String> params) {
        URL u = null;
        HttpURLConnection con = null;
        // 构建请求参数
        StringBuilder sb = new StringBuilder();
        if (params != null) {
            for (Entry<String, String> e : params.entrySet()) {
                sb.append(e.getKey());
                sb.append("=");
                sb.append(e.getValue());
                sb.append("&");
            }
            sb.deleteCharAt(sb.length() - 1);
        }
        System.out.println(sb.toString());
        LOGGER.warn("send_url:" + url + ";  send_data:" + sb.toString());
        // 尝试发送请求
        try {
            u = new URL(url);
            con = (HttpURLConnection) u.openConnection();
            //// POST 只能为大写，严格限制，post会不识别
            con.setRequestMethod("POST");
            con.setDoOutput(true);
            con.setDoInput(true);
            con.setUseCaches(false);
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
            osw.write(sb.toString());
            osw.flush();
            osw.close();
        } catch (Exception e) {

            LOGGER.error("doPostForm网络连接失败" + e.getMessage());
        } finally {
            if (con != null) {
                con.disconnect();
            }
        }

        // 读取返回内容
        StringBuffer buffer = new StringBuffer();
        try {
            //一定要有返回值，否则无法把请求发送给server端。
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
            String temp;
            while ((temp = br.readLine()) != null) {
                buffer.append(temp);
                buffer.append("\n");
            }
        } catch (Exception e) {

        }
        return buffer.toString();
    }

    public static String postFormForPro(String url, Map<String, Object> params) {
        URL u = null;
        HttpURLConnection con = null;
        // 构建请求参数
        StringBuilder sb = new StringBuilder();
        if (params != null) {
            for (Entry<String, Object> e : params.entrySet()) {
                if (e.getKey().equals("order_pic_n")) {
                    ArrayList arr = (ArrayList) e.getValue();
                    for (int i = 0; i < arr.size(); i++) {
                        sb.append("order_pic_n[]");
                        sb.append("=");
                        try {
                            sb.append(URLEncoder.encode(arr.get(i) + "", "utf-8") + "".trim());
                        } catch (UnsupportedEncodingException ex) {
                            LOGGER.error("request字段编码失败" + ex.getMessage());
                        }
                        sb.append("&");
                    }
                    continue;
                }
                sb.append(e.getKey());
                sb.append("=");
                sb.append(e.getValue());
                sb.append("&");
            }
            sb.deleteCharAt(sb.length() - 1);
        }
        LOGGER.warn("send_url:" + url + ";  send_data:" + sb.toString());
        // 尝试发送请求
        try {
            u = new URL(url);
            con = (HttpURLConnection) u.openConnection();
            //// POST 只能为大写，严格限制，post会不识别
            con.setRequestMethod("POST");
            con.setDoOutput(true);
            con.setDoInput(true);
            con.setUseCaches(false);
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
            osw.write(sb.toString());
            osw.flush();
            osw.close();
        } catch (Exception e) {

            LOGGER.error("doPostForm网络连接失败" + e.getMessage());
        } finally {
            if (con != null) {
                con.disconnect();
            }
        }

        // 读取返回内容
        StringBuffer buffer = new StringBuffer();
        try {
            //一定要有返回值，否则无法把请求发送给server端。
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
            String temp;
            while ((temp = br.readLine()) != null) {
                buffer.append(temp);
                buffer.append("\n");
            }
        } catch (Exception e) {
            LOGGER.error("调取网络连接失败" + e.getMessage());
        }
        return buffer.toString();
    }


//    public static Map<String, String> httpPostRequest2(String url, List<MultipartFile> multipartFiles, String fileParName,
//                                                       Map<String, Object> params, int timeout) {
//        Map<String, String> resultMap = new HashMap<String, String>();
//        CloseableHttpClient httpClient = HttpClients.createDefault();
//        String result = "";
//        try {
//            HttpPost httpPost = new HttpPost(url);
//            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
//            builder.setCharset(java.nio.charset.Charset.forName("UTF-8"));
//            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//            String fileName = null;
//            MultipartFile multipartFile = null;
//            for (int i = 0; i < multipartFiles.size(); i++) {
//                multipartFile = multipartFiles.get(i);
//                fileName = multipartFile.getOriginalFilename();
//                builder.addBinaryBody(fileParName, multipartFile.getInputStream(), ContentType.MULTIPART_FORM_DATA, fileName);// 文件流
//            }
//            //决中文乱码
//            ContentType contentType = ContentType.create(HTTP.PLAIN_TEXT_TYPE, HTTP.UTF_8);
//            for (Map.Entry<String, Object> entry : params.entrySet()) {
//                if(entry.getValue() == null){
//                    continue;
//                }
//                // 类似浏览器表单提交，对应input的name和value
//                builder.addTextBody(entry.getKey(), entry.getValue().toString(), contentType);
//            }
//            HttpEntity entity = builder.build();
//            httpPost.setEntity(entity);
//            HttpResponse response = httpClient.execute(httpPost);// 执行提交
//
//            // 设置连接超时时间
//            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeout)
//                    .setConnectionRequestTimeout(timeout).setSocketTimeout(timeout).build();
//            httpPost.setConfig(requestConfig);
//
//            HttpEntity responseEntity = response.getEntity();
//            resultMap.put("scode", String.valueOf(response.getStatusLine().getStatusCode()));
//            resultMap.put("data", "");
//            if (responseEntity != null) {
//                // 将响应内容转换为字符串
//                result = EntityUtils.toString(responseEntity, java.nio.charset.Charset.forName("UTF-8"));
//                resultMap.put("data", result);
//            }
//        } catch (Exception e) {
//            resultMap.put("scode", "error");
//            resultMap.put("data", "HTTP请求出现异常: " + e.getMessage());
//
//            Writer w = new StringWriter();
//            e.printStackTrace(new PrintWriter(w));
////            logger.error("HTTP请求出现异常: " + w.toString());
//        } finally {
//            try {
//                httpClient.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//        return resultMap;
//    }
}
